#include "EditorCallStackAbilityView.h"

#include "EditorCallStackAbilityViewModel.h"

#include "Widgets/Positioners/VerticalPositionerWidget.h"
#include "Widgets/RectangleWidget.h"
#include "Widgets/TextWidget.h"
#include "Widgets/Mouse/MouseWidget.h"

#include "Framework/Editor.h"
#include "Theme/EditorTheme.h"

void REditorCallStackAbilityView::BindViewModel(TSharedObjectPtr<REditorAbilityViewModel> InViewModel)
{
    Super::BindViewModel(InViewModel);
    CallStackViewModel = InViewModel;
}

void REditorCallStackAbilityView::FillOperations(TSharedObjectPtr<RWidget> InTitleBar)
{
}



void REditorCallStackAbilityView::CreateWidget(TSharedObjectPtr<RWidget> InParent)
{
    auto Root=NewWidget<RWidget>(InParent);
    Root->Anchor.Fill(InParent);

    List=NewWidget<RVerticalPositionerWidget>(Root);
    List->Anchor.Fill(Root);

    CallStackViewModel->OnCallStackChanged.Bind([this]()
    {
        FillCallStack();
    });
}

void REditorCallStackAbilityView::FillCallStack()
{
    List->ClearSubWidgets();

    const float LineHeight=20;

    for(int64_t i=0;i<CallStackViewModel->GetCallStackFrameNum();i++)
    {
        auto Frame=NewWidget<RWidget>(List);
        Frame->Height=LineHeight;
        Frame->Anchor.HorizontalFill(List);
        
        auto FrameHovor=NewWidget<RRectangleWidget>(Frame);
        FrameHovor->Anchor.Fill(Frame);
        FrameHovor->FillColor=REditor::Get()->CurrentTheme->ItemHoverColor;
        FrameHovor->Visible=[this,i]()
        {
            return CallStackViewModel->IsFrameHovered(i);
        };

        auto FrameSelected=NewWidget<RRectangleWidget>(Frame);
        FrameSelected->Anchor.Fill(Frame);
        FrameSelected->FillColor=REditor::Get()->CurrentTheme->ItemSelectColor;
        FrameSelected->Visible=[this,i]()
        {
            return CallStackViewModel->IsFrameSelected(i);
        };

        auto FunctionName=NewWidget<RTextWidget>(Frame);
        FunctionName->Anchor.VerticalFill(Frame);
        FunctionName->Anchor.LeftReference=Frame;
        FunctionName->Text=
            CallStackViewModel->GetCallStackFrameFunctionName(i)
            +U" "
            +CallStackViewModel->GetCallStackFrameFileName(i)
            ;
        FunctionName->VerticalAlignment=ETextVerticalAlignment::Center;
       
        auto Line = NewWidget<RRectangleWidget>(Frame);
        Line->Height= LineHeight;
        Line->Anchor.RightReference=Frame;
        Line->Anchor.RightOffset= 5;
        Line->Radius=LineHeight*0.5;
        Line->FillColor=REditor::Get()->CurrentTheme->TextBackgroundColor;

        FunctionName->Anchor.RightReference=Line;
        FunctionName->Anchor.RightOffset=5;
        FunctionName->Anchor.RightReferenceEdge=EHorizontalWidgetEdge::Left;

        auto LineText = NewWidget<RTextWidget>(Line);
        LineText->Anchor.CenterIn(Line);
        LineText->Text=[this,i]()
        {
            return CString(CallStackViewModel->GetCallStackFrameLineNumber(i)+1);
        };
        LineText->VerticalAlignment=ETextVerticalAlignment::Center;
        LineText->HorizontalAlignment=ETextHorizontalAlignment::Center;

        Line->Width=[LineText]()
        {
            return LineText->GetTextSize().X+10;
        };

        auto Mouse = NewWidget<RMouseWidget>(Frame);
        Mouse->Anchor.Fill(Frame);
        Mouse->OnClicked.BindLambda([this,i](const SMouseButtonEvent&)->bool
        {
            CallStackViewModel->OnFrameClicked(i);
            return true;
        });

        Mouse->OnEntered.BindLambda([this,i]()
        {
            CallStackViewModel->HoverFrame(i);
        });

        Mouse->OnExited.BindLambda([this,i]()
        {
            CallStackViewModel->UnhoverFrame(i);
        });


    }
}